﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Modbus.Device;

namespace xpds_ProductMonitor.Modbus
{
    internal class RTU
    {
        public static RTU Instannce;

        public static SerialInfo SerialInfo;

        SerialPort serialPort;

        private RTU(SerialInfo serialInfo)
        {
            serialPort = new SerialPort();
            SerialInfo = serialInfo;
            serialPort.PortName = serialInfo.PortName;
            serialPort.BaudRate = serialInfo.BaudRate;
            serialPort.Parity = serialInfo.Parity;
            serialPort.DataBits = serialInfo.DataBit;
            serialPort.StopBits = serialInfo.StopBits;
        }
        /// <summary>
        /// 单例获取RTU实例
        /// </summary>
        /// <param name="serialInfo"></param>
        /// <returns></returns>
        public static RTU getInstance(SerialInfo serialInfo)
        {
            lock ("RTU")
            {
                if (Instannce == null)
                {
                    Instannce = new RTU(serialInfo);
                }
                return Instannce;
            }
        }

        //关闭连接
        public void Close()
        {
            if (serialPort.IsOpen)
            {
                serialPort.Close();
                serialPort.Dispose();
                serialPort = null;
            }
        }

        /// <summary>
        /// 读取线圈状态(01功能码)
        /// </summary>
        /// <param name="slaveId"></param>
        /// <param name="startAddress"></param>
        /// <param name="readLen"></param>
        public bool[] ReadColiStatus(byte slaveId, ushort startAddress, ushort readLen)
        {
            bool[] result;
            using (serialPort)
            {
                try
                {
                    //打开串口
                    serialPort.Open();
                    var master = ModbusSerialMaster.CreateRtu(serialPort);
                    //读取数据
                     result = master.ReadCoils(slaveId, startAddress, readLen);
                }
                catch (Exception e)
                {
                    throw new Exception("串口连接或读取错误");
                }
                return result;
            }
        }

        //读取保持寄存器(03功能码)
        public ushort[] ReadHoldRegister(byte slaveId, ushort startAddress, ushort readLen)
        {
            ushort[] result;
            using (SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One))
            {
                try
                {
                    serialPort.Open();
                    var master = ModbusSerialMaster.CreateRtu(serialPort); 
                    result = master.ReadHoldingRegisters(slaveId, startAddress, readLen);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw new Exception("串口连接或读取错误");
                }
                return result;
            }
        }

        //写保持寄存器(06功能码)
        public void WriteHoldRegister(byte slaveId, ushort startAddress, ushort[] writeValues)
        {
            using (serialPort)
            {
                try
                { 
                    serialPort.Open();
                    var master = ModbusSerialMaster.CreateRtu(serialPort);
                    master.WriteMultipleRegisters(slaveId, startAddress, writeValues);
                }
                catch (Exception e)
                {
                    throw new Exception("串口连接或写入错误");
                }
            }
        }

        //在保持寄存器写多个值(16功能码)
        public void WriteHoldRegister(byte slaveId, ushort startAddress, ushort writeValue)
        {
            using (serialPort)
            {
                try
                {
                    serialPort.Open();
                    var master = ModbusSerialMaster.CreateRtu(serialPort);
                    master.WriteSingleRegister(slaveId, startAddress, writeValue);
                }
                catch (Exception e)
                {
                    throw new Exception("串口连接或写入错误");
                }
            }
        }





        
    }
}
